import cloud from "@lafjs/cloud";
const db = cloud.database();
import {
  resultOk,
  getPermissions,
  checkPermission,
  resultFail,
  isEmptyObject,
  listToTree
} from "@/utils";
const permissionName = "admin:dept";
const adminDbName = "dept";
interface Action {
  [key: string]: {
    method: string[];
    auth: boolean;
    permissions?: boolean;
    handler: Function;
  };
}

const actions: Action = {};
// 创建
actions.create = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    // check params
    const { name, parentDeptId, sort, status } = ctx.body;
    if (!name || !parentDeptId) {
      return resultFail("必传参数不能为空");
    }

    // check exist
    const { total } = await db.collection(adminDbName).where({ name }).count();
    if (total > 0) {
      return resultFail("部门已存在");
    }

    // add admin
    const r = await db.collection(adminDbName).add({
      name,
      parentDeptId,
      sort,
      status,
      created_at: new Date().getTime(),
      updated_at: new Date().getTime()
    });
    return resultOk(r);
  }
};
//删除
actions.delete = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    // check params
    const { id } = ctx.body;
    if (!id) {
      return resultFail("id不能为空");
    }

    // check id
    const { data: admin } = await db
      .collection(adminDbName)
      .where({ _id: id })
      .getOne();
    if (!admin) {
      return resultFail("无此部门");
    }
    // delete
    const r = await db.collection(adminDbName).doc(id).remove();
    return resultOk(r);
  }
};
//列表
actions.list = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    const { currentPage = 1, pageSize = 20, name, status } = ctx.body;
    // 数据库操作
    const db = cloud.database();
    const { total } = await db.collection(adminDbName).count();
    const where: { name?: any; status?: Boolean } = {};

    if (name) {
      const nameQuery = `/${name}/`;
      where.name = { $regex: nameQuery };
    }
    if (status) {
      where.status = status === 0;
    }
    const skip = currentPage === 0 ? 0 : currentPage - 1;
    let dbSelect = db
      .collection(adminDbName)
      .skip(skip * pageSize)
      .limit(pageSize);
    if (!isEmptyObject(where)) {
      dbSelect = dbSelect.where(where);
    }
    const r = await dbSelect.get();
    return resultOk({
      list: r.data.map(res => {
        res.id = res._id;
        return res;
      }),
      currentPage,
      pageSize,
      pageCount: Math.ceil(total / pageSize)
    });
  }
};
//获取单个信息
actions.info = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    const { data: admin } = await db
      .collection(adminDbName)
      .where({ _id: ctx.body.id })
      .getOne();

    delete admin["password"];
    const { permissions } = await getPermissions(admin._id);
    return resultOk({
      ...admin,
      permissions
    });
  }
};
actions.tree = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler() {
    // 数据库操作
    const db = cloud.database();
    const r = await db.collection(adminDbName).get();

    return resultOk({
      result: listToTree(
        r.data.map(_ => {
          _.id = _._id;
          _.children = [];
          return _;
        }),
        "id",
        "parentDeptId"
      )
    });
  }
};
//更新
actions.update = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    // 参数验证
    const { id } = ctx.body;
    if (!id) {
      return resultFail("数据不存在");
    }
    const items = { ...ctx.body };
    delete items.id;
    delete items._id;
    delete items.children;
    const r = await db
      .collection(adminDbName)
      .where({ _id: ctx.body.id })
      .update({
        ...items,
        updated_at: new Date().getTime()
      });
    return resultOk(r);
  }
};

// 入口，拦截器
export default async function (ctx: FunctionContext) {
  const { action } = ctx.query;

  // 黑名单处理和访问频率处理，此处省去。见帖子：https://forum.laf.run/d/130/7
  // 顺便说一下，黑名单的处理可以放在`__interceptor__`中，这里仅处理频率问题即可。

  // 没有 action 或没找到 action 报错
  if (!action || !actions[action]) {
    return resultFail("请求失败");
  }

  const { method, auth, handler, permissions } = actions[action];

  // method 不符
  if (!method.includes(ctx.method)) {
    return resultFail("请求失败");
  }

  // 鉴权
  if (auth && ctx.user === null) {
    return resultFail("用户未登陆", -2);
  }

  if (
    permissions &&
    !checkPermission(ctx.user, `${permissionName}:${action}`)
  ) {
    return resultFail("未授权访问");
  }

  // 执行
  if (handler) {
    return await handler(ctx);
  }

  // 能执行到这里肯定哪儿写错了
  return resultFail("请求失败");
}
